local sharedLibs = game.ReplicatedStorage.SharedLibs;
local oo = require(sharedLibs.BaseLib)

ISource = require(script.Parent.Parent.ISource);
AABB = require(script.Parent.AABB);
MathUtil = require(script.Parent.MathUtil);

BlockArea = require(script.Parent.BlockArea);
CylinderArea = require(script.Parent.CylinderArea);

local RandF = MathUtil.RandF;

--[[
	Region是一个不规则的区域，它包含多个Area。你可以检测一个点是否在Region内。
	也可以犯规Region内的任意一个随机点。
	
	可以利用这些 part 来构造一个Area
		立方体
		球体
		圆柱体
	
	也可以利用一些数学图形来构造，例如
		CircleXZ
		Sphere
		Cylinder
	
	Region除了提供了ISource接口外，可以检测一个point是否在Region内。
]]
local Region = oo.class("Region");
Region:implements(ISource);

function Region:constructor(name)
	self.name = name;
	self.GetNext = oo.bind(self._getNext, self);
	
	self._areas = {};
end

function Region:_getNext()
	local count = #self._areas;  
	if count == 0 then		
		return nil;
	else
		--- 随机取一个点
		local rndRegion = self._areas[math.random(count)]; 
		return rndRegion:GetRndPt();
	end
end

function Region:GetRndPt()
	return self:_getNext();
end

function Region:GetRandPtV3()
	return self:_getNext();
end

function Region:CheckPt(pt)
	for _, area in ipairs(self._areas) do
		if area:CheckPt(pt) then
			return true;
		end
	end
	return false;
end

function Region:CheckPtXZ(pt)
	for _, area in ipairs(self._areas) do
		if area:CheckPtXZ(pt) then
			return true;
		end
	end
	return false;
end

--- 通过n个基本几何体来构造一个Region（暂时只支持立方体part）
--- 注意：暂时只支持静态的part！！！
function Region.FromParts(...)
	local region = Region.new();
	region:BuildByParts(...);
	return region;	
end

function Region.FromFolderParts(folder)
	local children = folder:GetChildren();
	return Region.FromParts(table.unpack(children));	
end

function Region:BuildByParts(...)
	local parts = {...};
	for _, part in ipairs(parts) do
		if part.Shape == Enum.PartType.Block then
			table.insert(self._areas, BlockArea.new(part));
		elseif part.Shape == Enum.PartType.Cylinder then
			table.insert(self._areas, CylinderArea.new(part));
		end
	end
end

return Region;